package com.zw.yzk.kabu.data.repository;


import com.zw.yzk.kabu.data.network.entity.Entity;
import com.zw.yzk.kabu.data.network.task.Task;
import com.zw.yzk.kabu.data.cache.db.DataBaseManager;
import com.zw.yzk.kabu.data.cache.db.User;
import com.zw.yzk.kabu.data.constant.Constant;
import com.zw.yzk.kabu.data.exception.CustomException;
import com.zw.yzk.kabu.domain.repository.Repository;


import rx.Observable;
import rx.functions.Func1;

/**
 * Created by wei on 2016/12/23.
 */
public abstract class CommonRepository implements Repository {

    @Override
    public final <T> Observable observe(T t) {
        return Observable.just(createTask(t)).flatMap(new Func1<Task, Observable<?>>() {
            @Override
            public Observable<?> call(Task t) {
                return commonObserve(t);
            }
        });
    }

    /**
     * 将t转化为Task对象
     *
     * @param t   网络参数
     * @param <T>
     * @return Task对象
     */
    private <T> Task createTask(T t) {
        if (t == null) {
            return new Task();
        } else if (t instanceof Task) {
            return (Task) t;
        } else {
            return new Task();
        }
    }

    /**
     * 网络请求
     *
     * @param task 可转化为JSON字符串的数据结构
     * @return 网络数据返回
     */
    protected abstract Observable connectServer(Task task);

    /**
     * 从服务器返回中取出需要的数据
     *
     * @return
     */
    protected abstract Func1<? extends Entity, Observable> getServerData();

    /**
     * 用于发起网络请求
     *
     * @param task 网络参数
     * @return 网络数据
     */
    protected Observable commonObserve(Task task) {
        return Observable.just(task).flatMap(new Func1<Task, Observable<? extends Entity>>() {
            @Override
            public Observable<Entity> call(Task task) {
                return connectServer(addToken(task))
                        .map(checkServerData())
                        .flatMap(getServerData());
            }
        });
    }

    /**
     * 校验服务器数据
     *
     * @return 验证过后的JSON数据结构
     */
    private Func1<Entity, Entity> checkServerData() {
        return new Func1<Entity, Entity>() {
            @Override
            public Entity call(Entity entity) {
                if (entity == null) {
                    //解析数据失败
                    throw new CustomException(Constant.PARSE_ERROR);
                } else if (entity.errCode == Constant.RESULT_OK) {
                    return entity;
                } else if (entity.errCode == Constant.UNKNOWN_INVALID_TOKEN) {
                    throw new CustomException(Constant.UNKNOWN_INVALID_TOKEN);
                } else if (entity.errCode == Constant.MUST_LOGIN) {
                    throw new CustomException(Constant.MUST_LOGIN);
                } else {
                    throw new CustomException(entity.errCode, entity.msg);
                }
            }
        };
    }

    /**
     * 将BaseTask 在baseTask中添加用户token信息
     *
     * @param task 网络请求参数格式
     * @return task参数
     */
    protected Task addToken(Task task) {
        User user = DataBaseManager.getInstance().getLoginUser();
        if (user != null && user.isLogin()) {
            task.accessToken = user.getAccessToken();
            task.userId = String.valueOf(user.getUserId());
        } else {
            task.accessToken = null;
            task.userId = null;
        }
        return task;
    }

}
